package com.sun.volatiles;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 测试volatile不保证原子性
 */
public class AtomVolatile {
    public static void main(String[] args) {
        MyDataAtom myDataAtom = new MyDataAtom();
        for(int i =1; i<=20 ; i++){
            new Thread(()->{
            for(int j = 1; j <= 1000; j++){
                myDataAtom.addplus(); //不保证原子性
                myDataAtom.getMyAtomic(); //保证原子性
            }
            },String.valueOf(i)).start();
        }
        //多线程控制上面程序计算时间最好的方式，等待上面的计算完成再执行下面
      while(Thread.activeCount()>2){
          //Thread.activeCount()>2说明线程还没有计算完成
                  Thread.yield();
           //默认有两个线程
      }

        System.out.println(Thread.currentThread().getName()+"\t int type, finally num value :"+myDataAtom.num);
        System.out.println(Thread.currentThread().getName()+"\t  AtomicInteger type, finally num value :"+myDataAtom.atomicInteger);
      //运行测试后发现值不会到达20000，说明线程不安全，出现了丢失数据的情况33

    }
}
/*
 *1.验证volatile的可见性
 * 1.1假如int num = 0； num变量添加volatile关键字修饰,具有可见性
 * 2.验证volatile不保证原子性：
 *   原子性是指不可分割，完整性，也即某个线程者正在做某个业务时，中间不可以被加塞或分割，需要具有完整性
 *   要么同时成功，要么同时失败
 * */
class MyDataAtom{
    volatile int num = 0;

    public void addNum(){
        this.num=60;
    }
    //这里得变量添加了volatile关键字,volatile不保证原子性
    public void addplus(){
        num++;
    }
    AtomicInteger atomicInteger = new AtomicInteger();
    public void getMyAtomic(){
        atomicInteger.getAndIncrement();
    }
}